package br.com.dips.dao;

import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import br.com.dips.enums.Atribuicao;
import br.com.dips.model.Usuario;
import br.com.dips.model.UsuarioOrganizacao;

public class UsuarioDAO extends BaseDAO {

	@SuppressWarnings("unchecked")
	public Usuario consultar(Integer id) {
		EntityManager em = this.getEm();

		Query query = em.createNamedQuery("Usuario.findById", Usuario.class);
		query.setParameter("id", id);

		Query queryFindOrganizacoes = em.createQuery("select distinct orgUsr from UsuarioOrganizacao orgUsr left join fetch orgUsr.atribuicoes where orgUsr.usuario.id = :id");
		queryFindOrganizacoes.setParameter("id", id);

		Usuario usuario = (Usuario) query.getSingleResult();
		usuario.setOrganizacoes(queryFindOrganizacoes.getResultList());

		return usuario;
	}

	public Usuario incluir(Usuario usuario) {
		EntityManager em = this.getEm();
		em.persist(usuario);
		em.refresh(usuario);
		return usuario;
	}

	public void alterar(Usuario usuario) {
		EntityManager em = this.getEm();
		
		Query query = em.createQuery("delete from AtribuicaoUsuarioOrganizacao atrUsrOrg where atrUsrOrg.usuarioOrganizacao in (select usrOrg from UsuarioOrganizacao usrOrg where usrOrg.usuario.id = :id)");
		query.setParameter("id", usuario.getId());
		query.executeUpdate();
		
		query = em.createQuery("delete from UsuarioOrganizacao usuarioOrg where usuarioOrg.usuario.id = :id");
		query.setParameter("id", usuario.getId());
		query.executeUpdate();

		em.merge(usuario);
	}

	@SuppressWarnings("unchecked")
	public List<Usuario> listar(int idOrg, int start, int pageSize, String sortField, String sortOrder, Map<String, String> filters) {
		StringBuffer jpqlQuery = new StringBuffer("select usuario from Usuario usuario ");
		jpqlQuery.append(" where usuario not in (select distinct atrUsrOrg.usuarioOrganizacao.usuario from AtribuicaoUsuarioOrganizacao atrUsrOrg where atrUsrOrg.atribuicao = :root) ");
		
		if(idOrg > 0) {
			jpqlQuery.append(" and usuario in (select usrOrg.usuario from UsuarioOrganizacao usrOrg where usrOrg.organizacao.id = :idOrg) ");
		}
		
		if (filters != null & !filters.isEmpty()) {
			for (String key : filters.keySet()) {
				jpqlQuery.append(" and UPPER(usuario." + key + ") like '%" + filters.get(key).toUpperCase() + "%' ");
			}
		}

		if (sortField != null && !"".equals(sortField)) {
			jpqlQuery.append(" order by UPPER(usuario." + sortField + ") ");

			if (sortOrder != null && !"".equals(sortOrder) && !"UNSORTED".equals(sortOrder)) {
				jpqlQuery.append("ASCENDING".equals(sortOrder) ? "asc" : "desc");
			}

			jpqlQuery.append(", usuario.id ");

			if (sortOrder != null && !"".equals(sortOrder) && !"UNSORTED".equals(sortOrder)) {
				jpqlQuery.append("ASCENDING".equals(sortOrder) ? "asc" : "desc");
			}
		}

		Query query = this.getEm().createQuery(jpqlQuery.toString());
		query.setParameter("root", Atribuicao.ROOT);
		if(idOrg > 0) {
			query.setParameter("idOrg", idOrg);
		}
		query.setFirstResult(start);
		query.setMaxResults(pageSize);
		return query.getResultList();
	}

	public int conta(Map<String, String> filters) {
		StringBuffer jpqlQuery = new StringBuffer("select COUNT(usuario) from Usuario usuario ");
		jpqlQuery.append(" where usuario not in (select distinct atrUsrOrg.usuarioOrganizacao.usuario from AtribuicaoUsuarioOrganizacao atrUsrOrg where atrUsrOrg.atribuicao = :root) ");
		
		if (filters != null & !filters.isEmpty()) {
			for (String key : filters.keySet()) {
				jpqlQuery.append(" and UPPER(usuario." + key + ") like '%" + filters.get(key).toUpperCase() + "%'");
			}
		}

		Query query = this.getEm().createQuery(jpqlQuery.toString());
		query.setParameter("root", Atribuicao.ROOT);
		return ((Long) query.getSingleResult()).intValue();
	}

	@SuppressWarnings("unchecked")
	public UsuarioOrganizacao autentica(Integer idOrganizacao, String nomeUsuario, String senha) {
		EntityManager em = this.getEm();

		Query query = em.createNamedQuery("UsuarioOrganizacao.autenticacao", UsuarioOrganizacao.class);
		query.setParameter("idOrg", idOrganizacao);
		query.setParameter("nomeUsuario", nomeUsuario);
		query.setParameter("senha", senha);
		try {
			UsuarioOrganizacao usrOrg = (UsuarioOrganizacao) query.getSingleResult();
			
			Query queryFindOrganizacoes = em.createQuery("select orgUsr from UsuarioOrganizacao orgUsr left join fetch orgUsr.atribuicoes where orgUsr.usuario.id = :id");
			queryFindOrganizacoes.setParameter("id", usrOrg.getUsuario().getId());
			
			usrOrg.getUsuario().setOrganizacoes(queryFindOrganizacoes.getResultList());
			
			return usrOrg;
		} catch (NoResultException e) {
			// TODO: handle exception
		}

		return null;
	}

}
